package com.blog.service.meta.impl;

import com.blog.constant.ErrorConstant;
import com.blog.constant.Types;
import com.blog.constant.WebConst;
import com.blog.dto.MetaDto;
import com.blog.dto.cond.MetaCondition;
import com.blog.exception.BusinessException;
import com.blog.mapper.MetaMapper;
import com.blog.mapper.RelationshipMapper;
import com.blog.model.Content;
import com.blog.model.Meta;
import com.blog.model.Relationship;
import com.blog.service.content.ContentService;
import com.blog.service.meta.MetaService;
import com.blog.utils.MethodUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 项目服务层的业务接口
 *
 * @author wmb
 *
 * @since 2021-2-8
 */
@Service("metaService")
@Transactional
public class MetaServiceImpl implements MetaService {

    @Autowired
    @Qualifier("metaMapper")
    private MetaMapper metaMapper;

    @Autowired
    @Qualifier("relationshipMapper")
    private RelationshipMapper relationshipMapper;

    @Autowired
    @Qualifier("contentService")
    private ContentService contentService;

    /**
     * 根据条件获取对应的项目
     *
     * @param metaCondition
     *
     * @return
     */
    @Override
    @Cacheable(value = "metaCaches", key = "'metas_' + #p0")
    public List<Meta> getMetas(MetaCondition metaCondition) {
        return metaMapper.getMetasByMetaCondition(metaCondition);
    }

    /**
     * 批量添加
     *
     * @param cid
     * @param names
     * @param type
     */
    @Override
    @CacheEvict(value={"metaCache", "metaCaches"}, allEntries=true, beforeInvocation=true)
    public void saveMetas(Integer cid, String names, String type) {
        if (cid == null) {
            throw new BusinessException(ErrorConstant.PARAM_IS_NULL, MethodUtil.getLineInfo());
        }

        if (StringUtils.isNotBlank(names) && StringUtils.isNotBlank(type)) {
            String[] nameArray = names.split(",");
            for (String name: nameArray) {
                this.saveOrUpdate(cid, name, type);
            }
        }
    }

    /**
     * 添加或者更新
     *
     * @param cid
     * @param name
     * @param type
     */
    @Override
    @CacheEvict(value={"metaCache", "metaCaches"}, allEntries=true, beforeInvocation=true)
    public void saveOrUpdate(Integer cid, String name, String type) {
        MetaCondition metaCondition = new MetaCondition();
        metaCondition.setType(type);
        metaCondition.setName(name);
        List<Meta> metaList = this.getMetas(metaCondition);

        Integer mid;
        Meta meta = new Meta();
        if (metaList.size() == 1) {
            mid = metaList.get(0).getId();
        } else if (metaList.size() > 1) {
            throw new BusinessException(ErrorConstant.QUERY_META_IS_NOT_ONLY_ONE, MethodUtil.getLineInfo());
        } else {
            meta.setSlug(name);
            meta.setName(name);
            meta.setType(type);
            this.saveMeta(meta);
            mid = meta.getId();
        }

        if (mid != 0) {
            Long count = relationshipMapper.getCountById(cid, mid);
            if (count == 0) {
                Relationship relationship = new Relationship();
                relationship.setCid(cid);
                relationship.setMid(mid);
                relationshipMapper.saveRelationShip(relationship);
            }
        }
    }

    /**
     * 添加项目
     *
     * @param meta
     *
     * @return
     */
    @Override
    public void saveMeta(Meta meta) {
        if (meta == null) {
            throw new BusinessException(ErrorConstant.PARAM_IS_NULL, MethodUtil.getLineInfo());
        }
        metaMapper.saveMeta(meta);
    }

    /**
     * 根据类型查询项目列表，带项目下面的文章数
     *
     * @param type
     * @param orderBy
     * @param pageSize
     *
     * @return
     */
    @Override
    @Cacheable(value = "metaCaches", key = "'metaList_' + #p0")
    public List<MetaDto> getMetaList(String type, String orderBy, Integer pageSize) {
        if (StringUtils.isNotBlank(type)) {
            if (StringUtils.isBlank(orderBy)) {
                orderBy = "count desc, m.id desc";
            }
            if (pageSize < 1 || pageSize > WebConst.MAX_POSTS) {
                pageSize = 10;
            }
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("type", type);
            paramMap.put("order", orderBy);
            paramMap.put("pageSize", pageSize);
            return metaMapper.selectFromSql(paramMap);
        }
        return null;
    }

    /**
     * 添加
     *
     * @param type
     * @param name
     * @param id
     */
    @Override
    @CacheEvict(value={"metaCaches", "metaCache"}, allEntries=true, beforeInvocation=true)
    public void saveMeta(String type, String name, Integer id) {
        MetaCondition metaCondition = new MetaCondition();
        metaCondition.setName(name);
        metaCondition.setType(type);
        List<Meta> metaList = metaMapper.getMetasByMetaCondition(metaCondition);
        if (CollectionUtils.isEmpty(metaList)) {
            Meta meta = new Meta();
            meta.setName(name);
            if (id != null) {
                // 更新项目
                meta.setId(id);
                metaMapper.updateMeta(meta);

                // 更新原有的文章分类
                Meta metaFromDatabase = metaMapper.getMetaById(id);
                if (metaFromDatabase != null) {
                    contentService.updateCategory(meta.getName(), name);
                }
            } else {
                meta.setType(type);
                metaMapper.saveMeta(meta);
            }
        } else {
            throw new BusinessException(ErrorConstant.META_IS_EXISTS, MethodUtil.getLineInfo());
        }
    }

    /**
     * 删除项目
     *
     * @param id
     *
     * @return
     */
    @Override
    @CacheEvict(value={"metaCaches", "metaCache"}, allEntries=true, beforeInvocation=true)
    public void deleteMetaById(Integer id) {
        Meta meta = metaMapper.getMetaById(id);
        if (meta != null) {
            metaMapper.deleteMetaById(id);
            String type = meta.getType();
            String name = meta.getName();

            // 删除关联表数据
            List<Relationship> relationshipList = relationshipMapper.getRelationshipByMid(id);
            if (CollectionUtils.isNotEmpty(relationshipList)) {
                for (Relationship relationship: relationshipList) {
                    Content content = contentService.getArticleById(relationship.getCid());
                    if (content != null) {
                        Content tempContent = new Content();
                        tempContent.setId(content.getId());
                        if (type.equals(Types.CATEGORY.getType())) {
                            tempContent.setCategories(resetMeta(name, content.getCategories()));
                        }
                        if (type.equals(Types.TAG.getType())) {
                            tempContent.setTags(resetMeta(name, content.getTags()));
                        }
                        // 将删除的资源去除
                        contentService.updateArticleById(tempContent);
                    }
                }
                relationshipMapper.deleteRelationshipByMid(id);
            }
        }
    }

    private String resetMeta(String name, String metas) {
        String[] ms = StringUtils.split(metas, ",");
        StringBuilder sb = new StringBuilder();

        for (String m : ms) {
            if (!name.equals(m)) {
                sb.append(",").append(m);
            }
        }

        if (sb.length() > 0) {
            return sb.substring(1);
        }

        return "";
    }
}
